/*
 * Copyright 1999-2018 Alibaba Group Holding Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package site.shihuan.helpdesk.common.manager;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import site.shihuan.helpdesk.common.config.AuthConfigs;
import site.shihuan.helpdesk.common.model.JwtUser;

import java.util.*;

/**
 * JWT token manager.
 *
 * @author wfnuser
 * @author nkorange
 */
@Component
public class TokenManager {

    private static final String GLOBAL_ADMIN_KEY = "globalAdmin";

    private static final String UID_KEY = "uid";

    private static final String DEPT_ID_KEY = "deptId";

    private static final String TENANT_ID_KEY = "tenantId";

    private static final String ROLE_KEY = "roles";

    private static final String ROLE_ADMIN = "admin";

    private static final String ROLE_SPLIT = ",";

    @Autowired
    private AuthConfigs authConfigs;

    /**
     * Create token.
     *
     * @param jwtUser auth info
     * @return token
     */
    public String createToken(JwtUser jwtUser, Long expiration) {
        long now = System.currentTimeMillis();
        if (expiration == null) {
            expiration = authConfigs.getTokenValidityInSeconds();
        }
        Date validity;
        validity = new Date(now + expiration * 1000L);
        Map map = new HashMap();
        map.put(UID_KEY,jwtUser.getUid());
        map.put(TENANT_ID_KEY,jwtUser.getTenantId());
        map.put(DEPT_ID_KEY,jwtUser.getDeptId());
        map.put(ROLE_KEY,jwtUser.getRole());
        //检查是否为超级管理员
        for (String s : jwtUser.getRole().split(ROLE_SPLIT)) {
            if(ROLE_ADMIN.equals(s)) {
                map.put(GLOBAL_ADMIN_KEY,true);
                break;
            }
        }
        return Jwts.builder().setSubject("USER").setClaims(map).setExpiration(validity)
                .signWith(SignatureAlgorithm.HS256,authConfigs.getSecretKeyBytes()).compact();
    }

    /**
     * Get auth Info.
     *
     * @param token token
     * @return auth info
     */
    public JwtUser getUserInfo(String token) {
        if(token == null) {
            return null;
        }
        try {
            Claims claims = Jwts.parser().setSigningKey(authConfigs.getSecretKeyBytes())
                    .parseClaimsJws(token).getBody();
            return claimsToUser(claims);
        }catch (Exception e) {
            return null;
        }
    }

    /**
     * Claims To JwtUser
     *
     * @param claims claims
     * @return jwtUser
     */
    public JwtUser claimsToUser(Claims claims) {
        JwtUser jwtUser = new JwtUser();
        jwtUser.setUid(claims.get(UID_KEY,String.class));
        jwtUser.setDeptId(claims.get(DEPT_ID_KEY,String.class));
        jwtUser.setTenantId(claims.get(TENANT_ID_KEY,String.class));
        jwtUser.setRole(claims.get(ROLE_KEY,String.class));
        if(claims.get(GLOBAL_ADMIN_KEY) != null){
            jwtUser.setGlobalAdmin(true);
        }
        return jwtUser;
    }

    /**
     * validate token.
     *
     * @param token token
     */
    public void validateToken(String token) {
        Jwts.parser().setSigningKey(authConfigs.getSecretKeyBytes()).parseClaimsJws(token);
    }

}
